<?php

namespace App\Services;

use App\Models\User;
use App\Models\Order;
use App\Models\AffiliateLog;
use App\Models\AffiliateUser;
use App\Models\AffiliateOption;
use Throwable;

class PurchaseCommissionService
{
    public function cancelOrder(Order $order)
    {
        if (addon_is_activated('affiliate_system')) {
            try {
                \DB::beginTransaction();
                $logs = AffiliateLog::where('order_id', $order->id)->where('state', 'pending')->lockForUpdate()->get();
                if ($logs->count()) {
                    foreach ($logs as $log) {
                        $log->state = 'cancelled';
                        $log->saveOrFail();
                    }
                }
                \DB::commit();
            }catch(Throwable $ex) {
                \DB::rollBack();
                throw $ex;
            }
        }
    }
    
    public function confirmOrder(Order $order)
    {
        if (addon_is_activated('affiliate_system')) {
            try {
                \DB::beginTransaction();
                $logs = AffiliateLog::where('order_id', $order->id)->where('state', 'pending')->lockForUpdate()->get();
                if ($logs->count()) {
                    foreach ($logs as $log) {
                        $log_order_detail = \json_decode($log->order_detail, true);
                        if (!is_array($log_order_detail)) continue;
                        
                        $amount = '0.00';
                        foreach ($log_order_detail as $detail) {
                            if ($detail['status'] === 'confirmed') {
                                $amount = \bcadd($amount, \bcmul($detail['amount'], $detail['num'], 2), 2);
                                AffiliateUser::where('user_id', $log->user_id)->increment('balance', $detail['amount'] * $detail['num']);
                            }
                        }
                        $log->amount = $amount;
                        $log->state = 'confirmed';
                        $log->saveOrFail();
                    }
                }
                \DB::commit();
            }catch(Throwable $ex) {
                \DB::rollBack();
                throw $ex;
            }
        }
    }
    
    public function executeOrder(Order $order)
    {
        if (addon_is_activated('affiliate_system')) {
            
            try {
                \DB::beginTransaction();
                
                $first_purchase = Order::where('user_id', $order->user_id)->count() === 1;
                $sellers_commission_setting = AffiliateOption::where('type', 'sellers_commission_setting')->first();
                
                $user_registration_first_purchase = AffiliateOption::where('type', 'user_registration_first_purchase')->first();
                $product_sharing = AffiliateOption::where('type', 'product_sharing')->first();
                
                $commission_setting = [
                'seller' => \array_values(json_decode($sellers_commission_setting->details, true)),
                'customer' => [
                    'first' => empty($user_registration_first_purchase->status) ? [] : [
                            \json_decode($user_registration_first_purchase->details)->first_purchase_first_level_commission ?? 0, 
                            \json_decode($user_registration_first_purchase->details)->first_purchase_secondary_level_commission ?? 0, 
                            \json_decode($user_registration_first_purchase->details)->first_purchase_third_level_commission ?? 0, 
                    ],
                    'purchase' => empty($product_sharing->status) ? [] : [
                        [
                            \json_decode($product_sharing->details)->purchasing_first_level_amount,
                            \json_decode($product_sharing->details)->purchasing_first_level_amount_type,
                        ],
                        [
                            \json_decode($product_sharing->details)->purchasing_secondary_level_amount,
                            \json_decode($product_sharing->details)->purchasing_secondary_level_amount_type,
                        ],
                        [
                            \json_decode($product_sharing->details)->purchasing_third_level_amount,
                            \json_decode($product_sharing->details)->purchasing_third_level_amount_type,
                        ],
                    ]
                ]
                ];
                
                $seller_node = explode(',', User::whereRaw('FIND_IN_SET(?, node)', [$order->seller_id])->value('node'));
                array_pop($seller_node); 
                $seller_node = array_reverse($seller_node);
                
                $customer_node = explode(',', User::whereRaw('FIND_IN_SET(?, node)', [$order->user_id])->value('node'));
                array_pop($customer_node); 
                $customer_node = array_reverse($customer_node);
                
                \Log::info(var_export([
                    'order_id' => $order->id,
                    'seller_node' => $seller_node,
                    'customer_node' => $customer_node,
                ], true) . PHP_EOL);
                
                for($i = 0; $i < 3; $i++) {
                    if (\intval($sellers_commission_setting->status) === 1 && isset($seller_node[$i])) {
                        $user_id = $seller_node[$i];
                        $share_user_id = $order->seller_id;
                        
                        //Remove cross customer user
                        if ($seller_node[$i] != $order->user_id) {
                            
                            $key = array_search($user_id, $customer_node);
                            if ($key === false || $key >= 3 || \intval($key) > $i || (\intval($key) === $i && \in_array(User::where('id', $user_id)->value('user_type'), ['admin', 'seller']))) {
                                
                                $amount = \bcmul($order->grand_total, \bcdiv($commission_setting['seller'][$i], 100, 2), 2);
                                //AffiliateUser::where('user_id', $user_id)->increment('balance', $amount);
                                
                                
                                $order_detail = [];
                                foreach ($order->orderDetails as $details) {
                                    $order_detail[] = [
                                        'product_id' => $details->product->id,
                                        'num' => $details->quantity,
                                        'status' => 'confirmed',
                                        'amount' => \bcmul($details->product->unit_price, \bcdiv($commission_setting['seller'][$i], 100, 2), 2)
                                    ];
                                }
                                
                                
                                $affiliate_log = AffiliateLog::where('user_id', $user_id)->where('order_id', $order->id)->first();
                                if (!$affiliate_log) $affiliate_log = new AffiliateLog;
                                $affiliate_log->user_id = $user_id;
                                $affiliate_log->referred_by_user = $share_user_id;
                                $affiliate_log->amount = $amount;
                                $affiliate_log->order_id = $order->id;
                                $affiliate_log->order_detail = \json_encode($order_detail);
                                $affiliate_log->status = 1;
                                $affiliate_log->state = 'pending';
                                $affiliate_log->affiliate_type = 'product_sharing';
                                $affiliate_log->save();
                            }
                        }
                    }
                    if (!empty($user_registration_first_purchase->status) || !empty($product_sharing->status)) {
                        if (!isset($customer_node[$i])) continue;
                        $user_id = $customer_node[$i];
                        $share_user_id = $order->user_id;
                        
                        //Remove cross customer user
                        if ($customer_node[$i] != $order->seller_id) {
                            
                            $key = array_search($user_id, $seller_node);
                            if ($key === false || $key >= 3 || \intval($key) > $i || (\intval($key) === $i && \in_array(User::where('id', $user_id)->value('user_type'), ['customer']))) {
                            
                                if ($first_purchase) {
                                    if (isset($commission_setting['customer']['first'][$i]) && $commission_setting['customer']['first'][$i] > 0) {
                                        $amount = \bcmul($order->grand_total, \bcdiv($commission_setting['customer']['first'][$i], 100, 2), 2);
                                        //if ($state === 'confirmed') AffiliateUser::where('user_id', $user_id)->increment('balance', $amount);
                                        
                                        
                                        $order_detail = [];
                                        foreach ($order->orderDetails as $details) {
                                            $order_detail[] = [
                                                'product_id' => $details->product->id,
                                                'num' => $details->quantity,
                                                'status' => 'confirmed',
                                                'amount' => \bcmul($details->product->unit_price, \bcdiv($commission_setting['customer']['first'][$i], 100, 2), 2)
                                            ];
                                        }
                                        
                                        $affiliate_log = AffiliateLog::where('user_id', $user_id)->where('order_id', $order->id)->first();
                                        if (!$affiliate_log) $affiliate_log = new AffiliateLog;
                                        $affiliate_log->user_id = $user_id;
                                        $affiliate_log->referred_by_user = $share_user_id;
                                        $affiliate_log->amount = $amount;
                                        $affiliate_log->order_id = $order->id;
                                        $affiliate_log->order_detail = \json_encode($order_detail);
                                        $affiliate_log->status = 1;
                                        $affiliate_log->state = 'pending';
                                        $affiliate_log->affiliate_type = 'user_registration_first_purchase';
                                        $affiliate_log->save();
                                        
                                    }
                                } else {
                                    if (isset($commission_setting['customer']['purchase'][$i])) {
                                        list($value, $value_type) = $commission_setting['customer']['purchase'][$i];
                                        if ($value > 0) {
                                            $amount = ($value_type === '$' ? $value : \bcmul($order->grand_total, \bcdiv($value, 100, 2), 2));
                                            //if ($state === 'confirmed') AffiliateUser::where('user_id', $user_id)->increment('balance', $amount);
                                            
                                            $order_detail = [];
                                            foreach ($order->orderDetails as $details) {
                                                $order_detail[] = [
                                                    'product_id' => $details->product->id,
                                                    'num' => $details->quantity,
                                                    'status' => 'confirmed',
                                                    'amount' => ($value_type === '$' ? $value : \bcmul($details->product->unit_price, \bcdiv($value, 100, 2), 2))
                                                ];
                                            }
                                            
                                            $affiliate_log = AffiliateLog::where('user_id', $user_id)->where('order_id', $order->id)->first();
                                            if (!$affiliate_log) $affiliate_log = new AffiliateLog;
                                            $affiliate_log->user_id = $user_id;
                                            $affiliate_log->referred_by_user = $share_user_id;
                                            $affiliate_log->amount = $amount;
                                            $affiliate_log->order_id = $order->id;
                                            $affiliate_log->order_detail = \json_encode($order_detail);
                                            $affiliate_log->status = 1;
                                            $affiliate_log->state = 'pending';
                                            $affiliate_log->affiliate_type = 'product_sharing';
                                            $affiliate_log->save();
                                            
                                        }
                                    }
                                }
                            }
                            
                        }
                    }
                }
                
                \DB::commit();
            }catch(Throwable $ex) {
                \DB::rollBack();
                throw $ex;
            }
        }
    }
    
}